import os
import logging
from datetime import datetime
from typing import Dict

KEEP_FILE_CNT = 5

class LogCore:
    _log_id = -1  # 全局日志 ID
    _log_list_new: Dict[str, Dict] = {}  # 使用 _log_list_new 存储日志信息
    _console_enabled = False
    _logging_paused = False  # 新增：日志暂停标志

    @staticmethod
    def log_open(console_enable: bool):
        """初始化日志系统，是否启用控制台打印"""
        LogCore._console_enabled = console_enable

    @staticmethod
    def _get_next_log_file(log_dir: str, log_name: str, timestamp: str) -> str:
        """获取下一个日志文件名，按照后缀递增并使用指定时间戳"""
        index = 1
        while True:
            log_file = os.path.join(log_dir, f"{log_name}_{timestamp}_{index}.log")
            if not os.path.exists(log_file):
                return log_file
            index += 1

    @staticmethod
    def _delete_old_logs(log_dir: str, log_name: str, keep: int):
        """删除旧日志文件，只保留最新的指定数量"""
        log_files = [f for f in os.listdir(log_dir) if f.startswith(log_name) and f.endswith('.log')]
        log_files.sort(key=lambda f: os.path.getmtime(os.path.join(log_dir, f)))  # 按修改时间排序

        if len(log_files) > keep:
            for old_log in log_files[:-keep]:
                os.remove(os.path.join(log_dir, old_log))

    @staticmethod
    def log_register(log_name: str, max_lines: int = 100000, keep_file_cnt: int = KEEP_FILE_CNT) -> int:
        """
        注册日志，返回 log_id
        :param log_name: 日志名称
        :param max_lines: 单个日志文件的最大行数
        :param keep_file_cnt: 保留的日志文件数量
        :return: log_id
        """
        if log_name in LogCore._log_list_new:  # 如果已经注册过，则返回已注册的 log_id
            return LogCore._log_list_new[log_name]["id"]
        
        LogCore._log_id += 1
        log_id = LogCore._log_id

        # 创建日志路径
        now = datetime.now()
        log_dir = os.path.join(os.getcwd(), "log", now.strftime("%Y"), now.strftime("%m"), now.strftime("%m-%d"))
        os.makedirs(log_dir, exist_ok=True)  # 确保目录存在
        timestamp = now.strftime("%Y%m%d_%H%M%S")
        log_file = LogCore._get_next_log_file(log_dir, log_name, timestamp)  # 获取日志文件名

        # 删除旧日志文件
        LogCore._delete_old_logs(log_dir, log_name, keep_file_cnt)

        # 创建 Logger
        logger = logging.getLogger(log_name)
        logger.setLevel(logging.DEBUG)

        # 文件 Handler
        file_handler = logging.FileHandler(log_file, encoding="utf-8")
        file_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
        file_handler.addFilter(LogCore.LineCountFilter(log_id))  # 添加行数过滤器
        logger.addHandler(file_handler)

        # 控制台 Handler
        if LogCore._console_enabled:
            console_handler = logging.StreamHandler()
            console_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
            logger.addHandler(console_handler)

        # 保存 Logger 到 _log_list_new
        LogCore._log_list_new[log_name] = {
            "id": log_id,
            "object": logger,
            "time": now,  # 记录创建时间
            "max_lines": max_lines,
            "line_count": 0,
            "keep_file_cnt": keep_file_cnt,
            "current_date": now.date()  # 记录当前的日期
        }
        return log_id

    @staticmethod
    def log_unregister(log_name: str) -> int:
        """
        注销日志，返回 log_id
        :param log_name: 日志名称
        :return: log_id
        """
        if log_name in LogCore._log_list_new:
            log_id = LogCore._log_list_new[log_name]["id"]
            logger = LogCore._log_list_new[log_name]["object"]
            # 关闭并移除 Handlers
            for handler in logger.handlers[:]:
                handler.close()
                logger.removeHandler(handler)
            del LogCore._log_list_new[log_name]
            return log_id
        return -1

    @staticmethod
    def _check_and_rotate_date(logger: logging.Logger, log_id: int, log_info: Dict):
        """检查日期是否变化，若变化则新建日志文件"""
        current_date = datetime.now().date()
        if current_date != log_info["current_date"]:
            for handler in logger.handlers[:]:
                if isinstance(handler, logging.FileHandler):
                    # Get current year, month, and day
                    now = datetime.now()
                    log_dir = os.path.join(os.getcwd(), "log", now.strftime("%Y"), now.strftime("%m"), now.strftime("%m-%d"))
                    os.makedirs(log_dir, exist_ok=True)  # Ensure new directory exists
                    log_name = os.path.basename(handler.baseFilename).split('_')[0]
                    handler.close()
                    logger.removeHandler(handler)

                    # 使用当前日期创建新日志文件
                    timestamp = now.strftime("%Y%m%d_%H%M%S")
                    new_log_file = LogCore._get_next_log_file(log_dir, log_name, timestamp)
                    new_handler = logging.FileHandler(new_log_file, encoding="utf-8")
                    new_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
                    new_handler.addFilter(LogCore.LineCountFilter(log_id))
                    logger.addHandler(new_handler)

                    # 更新日期和行数
                    log_info["current_date"] = current_date
                    log_info["line_count"] = 0
                    LogCore._delete_old_logs(log_dir, log_name, log_info["keep_file_cnt"])
                    break

    @staticmethod
    def _log(log_id: int, level: str, msg: str):
        """通用日志记录逻辑"""
        print(msg)
        
        logger = None
        log_info = None
        for log_name, info in LogCore._log_list_new.items():
            if info["id"] == log_id:
                logger = info["object"]
                log_info = info
                break
        if not logger:
            raise ValueError(f"Logger 没有注册, log_id={log_id}")

        # 如果暂停且不是 error 日志，则丢弃 info 和 debug
        if LogCore._logging_paused and level not in ["error"]:
            return

        # 检查日期是否变化
        LogCore._check_and_rotate_date(logger, log_id, log_info)

        # 更新行数并检查是否需要换新文件
        log_info["line_count"] += 1
        if log_info["line_count"] > log_info["max_lines"]:
            LogCore._rotate_log_file(logger, log_id, log_info)

        log_method = getattr(logger, level, None)
        if log_method:
            log_method(msg)
            
        

    @staticmethod
    def _rotate_log_file(logger: logging.Logger, log_id: int, log_info: Dict):
        """更换日志文件（因行数超限）"""
        for handler in logger.handlers[:]:
            if isinstance(handler, logging.FileHandler):
                now = datetime.now()
                log_dir = os.path.join(os.getcwd(), "log", now.strftime("%Y"), now.strftime("%m"), now.strftime("%m-%d"))
                os.makedirs(log_dir, exist_ok=True)
                log_name = os.path.basename(handler.baseFilename).split('_')[0]
                handler.close()
                logger.removeHandler(handler)

                # 添加新的日志文件，使用当前时间戳
                timestamp = now.strftime("%Y%m%d_%H%M%S")
                new_log_file = LogCore._get_next_log_file(log_dir, log_name, timestamp)
                new_handler = logging.FileHandler(new_log_file, encoding="utf-8")
                new_handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
                new_handler.addFilter(LogCore.LineCountFilter(log_id))
                logger.addHandler(new_handler)

                log_info["line_count"] = 0  # 重置行计数器
                LogCore._delete_old_logs(log_dir, log_name, log_info["keep_file_cnt"])
                break

    @staticmethod
    def log_info(log_id: int, msg: str):
        LogCore._log(log_id, "info", msg)

    @staticmethod
    def log_warn(log_id: int, msg: str):
        LogCore._log(log_id, "warning", msg)

    @staticmethod
    def log_error(log_id: int, msg: str):
        LogCore._log(log_id, "error", msg)

    @staticmethod
    def log_debug(log_id: int, msg: str):
        LogCore._log(log_id, "debug", msg)

    @staticmethod
    def pause_logging():
        """暂停日志记录，info 和 debug 将被丢弃，error 立即记录"""
        LogCore._logging_paused = True

    @staticmethod
    def resume_logging():
        """恢复日志记录"""
        LogCore._logging_paused = False

    class LineCountFilter(logging.Filter):
        def __init__(self, log_id: int):
            super().__init__()
            self.log_id = log_id

        def filter(self, record):
            for log_info in LogCore._log_list_new.values():
                if log_info["id"] == self.log_id:
                    log_info["line_count"] += 1
                    break
            return True


class StatusLogger:
    _log_id = -1  # 单独的静态变量，用于记录本类的 log_id

    @staticmethod
    def Open(enable_console: bool = False, max_lines: int = 100000, keep_file_cnt: int = KEEP_FILE_CNT):
        """打开日志"""
        if enable_console:
            LogCore.log_open(console_enable=True)

        log_name = "StatusLog"
        StatusLogger._log_id = LogCore.log_register(log_name, max_lines, keep_file_cnt)
        if StatusLogger._log_id == -1:  # 检查日志是否成功注册
            raise RuntimeError(f"Failed to register logger for {log_name}")

    @staticmethod
    def update_date():
        day1 = datetime(2025, 3, 12, 10, 0, 0)
        LogCore._log_list_new["StatusLog"]["current_date"] = day1.date()

    @staticmethod
    def Close():
        """关闭日志"""
        if StatusLogger._log_id != -1:
            LogCore.log_unregister("StatusLog")
            StatusLogger._log_id = -1

    @staticmethod
    def Info(msg: str):
        """记录 INFO 日志"""
        LogCore.log_info(StatusLogger._log_id, msg)

    @staticmethod
    def Warn(msg: str):
        """记录 WARNING 日志"""
        LogCore.log_warn(StatusLogger._log_id, msg)

    @staticmethod
    def Error(msg: str):
        """记录 ERROR 日志"""
        LogCore.log_error(StatusLogger._log_id, msg)

    @staticmethod
    def Debug(msg: str):
        """记录 DEBUG 日志"""
        LogCore.log_debug(StatusLogger._log_id, msg)

    @staticmethod
    def Pause():
        """暂停 StatusLogger 的日志记录，info 和 debug 被丢弃，error 立即记录"""
        LogCore.pause_logging()

    @staticmethod
    def Resume():
        """恢复 StatusLogger 的日志记录"""
        LogCore.resume_logging()


class DeviceLogger:
    _log_id = -1  # 单独的静态变量，用于记录本类的 log_id

    @staticmethod
    def Open(enable_console: bool = False, max_lines: int = 100000, keep_file_cnt: int = KEEP_FILE_CNT):
        """打开日志"""
        if enable_console:
            LogCore.log_open(console_enable=True)

        log_name = "DeviceLog"
        DeviceLogger._log_id = LogCore.log_register(log_name, max_lines, keep_file_cnt)
        if DeviceLogger._log_id == -1:  # 检查日志是否成功注册
            raise RuntimeError(f"Failed to register logger for {log_name}")

    @staticmethod
    def Close():
        """关闭日志"""
        if DeviceLogger._log_id != -1:
            LogCore.log_unregister("DeviceLog")
            DeviceLogger._log_id = -1

    @staticmethod
    def Info(msg: str):
        """记录 INFO 日志"""
        LogCore.log_info(DeviceLogger._log_id, msg)

    @staticmethod
    def Warn(msg: str):
        """记录 WARNING 日志"""
        LogCore.log_warn(DeviceLogger._log_id, msg)

    @staticmethod
    def Error(msg: str):
        """记录 ERROR 日志"""
        LogCore.log_error(DeviceLogger._log_id, msg)

    @staticmethod
    def Debug(msg: str):
        """记录 DEBUG 日志"""
        LogCore.log_debug(DeviceLogger._log_id, msg)

    @staticmethod
    def Pause():
        """暂停 DeviceLogger 的日志记录，info 和 debug 被丢弃，error 立即记录"""
        LogCore.pause_logging()

    @staticmethod
    def Resume():
        """恢复 DeviceLogger 的日志记录"""
        LogCore.resume_logging()


class UILogger:
    _log_id = -1  # 单独的静态变量，用于记录本类的 log_id

    @staticmethod
    def Open(enable_console: bool = False, max_lines: int = 100000, keep_file_cnt: int = KEEP_FILE_CNT):
        """打开日志"""
        if enable_console:
            LogCore.log_open(console_enable=True)

        log_name = "UILog"
        UILogger._log_id = LogCore.log_register(log_name, max_lines, keep_file_cnt)
        if UILogger._log_id == -1:  # 检查日志是否成功注册
            raise RuntimeError(f"Failed to register logger for {log_name}")

    @staticmethod
    def Close():
        """关闭日志"""
        if UILogger._log_id != -1:
            LogCore.log_unregister("UILog")
            UILogger._log_id = -1

    @staticmethod
    def Info(msg: str):
        """记录 INFO 日志"""
        LogCore.log_info(UILogger._log_id, msg)

    @staticmethod
    def Warn(msg: str):
        """记录 WARNING 日志"""
        LogCore.log_warn(UILogger._log_id, msg)

    @staticmethod
    def Error(msg: str):
        """记录 ERROR 日志"""
        LogCore.log_error(UILogger._log_id, msg)

    @staticmethod
    def Debug(msg: str):
        """记录 DEBUG 日志"""
        LogCore.log_debug(UILogger._log_id, msg)

    @staticmethod
    def Pause():
        """暂停 DeviceLogger 的日志记录，info 和 debug 被丢弃，error 立即记录"""
        LogCore.pause_logging()

    @staticmethod
    def Resume():
        """恢复 DeviceLogger 的日志记录"""
        LogCore.resume_logging()